home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / misc / ppipc.lzh / Docs / IPC.Doc < prev    next >
Encoding:
Text File  |  1989-12-01  |  34.6 KB  |  664 lines

  1.  
  2.           An Inter-Process Communication Standard for the Amiga
  3.           =====================================================
  4.  
  5.                           -- November 1989 --
  6.  
  7.  
  8. This is initial documentation for the IPC standard developed largely in the
  9. course of some furious traffic over usenet during 1988.  The core of the
  10. standard is now stable (the IPCPort mechanism and the IPCMessage
  11. structure), but there is work still to be done on the details, on
  12. developing message IDs for specific functions, and on publishing them.
  13. Also elements such as the "Port Broker" need more development.
  14.  
  15. [There are no doubt still many gaps in this document.  I intend to fill
  16. them in as time goes on (and permits!), but please bring any egregious
  17. omissions to my attention.]
  18.  
  19.  
  20. Why IPC?
  21. ========
  22.  
  23. [Since the following paragraphs were written, ARexx has come into fairly
  24. widespread use, and is obviously an attractive way of tackling some kinds
  25. of IPC. However, the mechanism to be discussed here has a rather different
  26. focus, and can be used in situations where, for example, speed limits would
  27. rule out ARexx.  More will be said on this later.]
  28.  
  29. Up to now, even though the Amiga is the first really totally multitasking
  30. personal computer, programs for it have been written much as for any of the
  31. older one-job-at-a-time machines (though they often take good advantage of
  32. the windowing environment): they run as single processes.  A few programs
  33. spawn child tasks to perform some of their functions, but they are still
  34. monolithic in their design.
  35.  
  36. There is an alternative.  A ... let's call it a "Job environment"... could
  37. be serviced by a number of more specialized processes, communicating with
  38. each other.  Depending on the needs of that environment, these processes
  39. could be very specialized -- a note bender in a MIDI system, say -- or more
  40. general, like a text editor that called up things like a spell checker or
  41. output formatter when needed.  Such a system would give the user much more
  42. choice in configuring it to his/her preferences. (Not forgetting though
  43. that a default configuration would have to be as easy to use as any well
  44. designed program!)  The modules in an environment wouldn't all have to come
  45. from one company, as the interface to invoke a module's function would be
  46. published with the module.  You could add special purpose functions to a
  47. paint program say, just by starting up another process that would
  48. recognize, or be recognized by, the paint program.
  49.  
  50. There are a lot of possible applications of this principle, with widely
  51. varying requirements.  Here is a very incomplete list of a few that come to
  52. mind:
  53.  
  54.     *   Communications -- connect terminal emulators, protocol handlers
  55.                     [Kermit, XModem etc.], auto-answer modules, script
  56.                     processors etc. to suit the user's environment.
  57.                     [Note the wide range of parameters such as processing
  58.                     speed demanded by different modules: protocol handlers
  59.                     will have to operate character by character at baud
  60.                     rates, while script servers and auto-answer can be much
  61.                     more leisurely.]
  62.  
  63.     *   MIDI Modules -- a lot of possibilities here for a fast IPC
  64.                     protocol; anything you might want to do to a MIDI
  65.                     channel could be a "plug-in" module.
  66.  
  67.     *   Data Acquisition and Control -- there are untapped opportunities
  68.                     for a multitasking machine in the laboratory; being
  69.                     able to "plug" modules together like you can with lab
  70.                     equipment would be a great attraction.
  71.  
  72.     *   Desktop Publishing -- put together a comprehensive and competent
  73.                     system from the pieces YOU prefer.
  74.  
  75.     *   Desktop Video and Presentation -- lots of enticing possibilities
  76.                     here; the real-time nature of presentation gives lots
  77.                     of opportunities for fast IPC.  (One might even think
  78.                     of coupling several machines together...!)
  79.  
  80.     *   Service Programs -- to do common jobs for other modules; small ones
  81.                     -- print format servers, pattern matchers, directory
  82.                     searchers etc. -- can take a lot of the load off other
  83.                     modules that would otherwise have to include code for
  84.                     those things; larger ones could handle jobs like spell-
  85.                     checking for any program that wanted it.
  86.  
  87.     *   A Multitasking H*perC*rd -- a somewhat vaguely specified, but
  88.                     highly enticing, goal; dream your own scenario...
  89.  
  90.  
  91. This should give some flavor of the ways in which I think a general
  92. "Cooperating Processes Paradigm" would be a winner.  You can see that a
  93. wide range of schemes could fall under the term "IPC".  It would be nice if
  94. they could all be handled by one underlying protocol.
  95.  
  96. There are a number of possible candidates.  Processes can pass information
  97. between each other via files and pipes, for example.  This has the great
  98. advantage that it is already built into the system, but its disadvantage is
  99. the heavy overhead involved in file-type I/O; passing around large blocks
  100. (like bit maps) is probably ruled out. Also, simple serial stream,
  101. unstructured, communication isn't good enough for a system that is going to
  102. pass around many different types of information. The receiver of
  103. information has to know exactly what it is getting, and the sender must
  104. know exactly how to tell the receiver about it.
  105.  
  106. This means some kind of standard structure for the data that can be
  107. understood by all processes. IFF is such a standard, but again
  108. unfortunately it is too complex and serial-oriented for very fast
  109. communication.  Its principles make a good starting point though.
  110.  
  111. There is an obvious candidate built into the Amiga Exec: Messages and
  112. Ports.  These are actually just about what we want, but there are a couple
  113. of problems with them as they stand.
  114.  
  115. First, although ports work perfectly when child tasks spawned and managed
  116. by a single master process use them to talk to each other, there is no
  117. protection against accidents that are likely to occur when independent
  118. processes communicate.  The problem is that, as ports are accessed by a
  119. pointer, there is no way of being sure that the port pointed to still
  120. exists when you want it, unless you lock out all other processes before you
  121. get the pointer, and don't unlock them again until you've used it.  This
  122. can get VERY cumbersome and inefficient if you want to send a lot of
  123. messages to a port, as you have to do the Forbid/Find pointer/Use pointer/
  124. Permit sequence for every message.
  125.  
  126. Second, there is the problem of a process knowing exactly what is in the
  127. message it has received.  As we said, there must be a Standard Structure
  128. for the data in the message so that it becomes easy for different authors
  129. to write programs that can understand each other.
  130.  
  131. Hence the IPC Standard really breaks down into two parts: IPCPorts and
  132. IPCMessages.  These are essentially independent of each other, in that the
  133. Ports have no knowledge or concern about the message structure (aside from
  134. the necessity for the standard Exec Message structure at its heart), and
  135. conversely the Messages are not concerned with the Port procedures.
  136.  
  137. It should be pointed out that this is a "Foundation Level" protocol.  It
  138. defines how ports should be managed, and the common structure of messages,
  139. but says nothing more about how they are to be used.  There are many higher
  140. level considerations, such as how the processes should appear to the user,
  141. and how he is to control them, that need to be worked out.  There are a lot
  142. of possibilities here: control panels, patch panels, "drop-in" menus...;
  143. some applications will need added capabilities such as command languages
  144. and scripts; others would be slowed unacceptably by such overhead.  But
  145. with luck this standard will be general enough to cover the range.
  146.  
  147. There are other schemes, actual and potential, that have to be considered
  148. in relation to this one.  In general there is probably no need for them to
  149. be competitors.  One such is AREXX, which has already been successful in
  150. applications like integrating editors with text formatters; because it is
  151. basically an interpreted script language, it doesn't seem so suitable for
  152. some of the other potential applications mentioned above.  On the other
  153. hand, because it is a script language, it is more immediately accessible to
  154. the user than this IPC protocol, which only addresses the program
  155. level.  There seems no reason though why an interface between AREXX and
  156. this standard could not be written; only a restricted set of IPCMessages
  157. could be handled, but probably enough to give great flexibility.
  158.  
  159. One other thing this standard has in its favor.  It is Public Domain...
  160. I've put copyright marks in the code sources, but this is solely to
  161. discourage incompatible modifications.  Both the protocol and the library
  162. may be used in any program or product, for profit or otherwise, without
  163. fee.  The main thing I ask is that you treat any new message IDs you assign
  164. (see the next section) as similarly public, and try to keep as much
  165. standardization as possible in these.  Before defining any new IDs, see if
  166. the ones described in the "Standard IDs" document will do, and if not, pass
  167. the ones you create around (and specifically back to me! I guess I have to
  168. be the main repository at the moment).  When developing a set of IDs, try
  169. to think beyond the needs of the moment (this ain't always easy!).  If you
  170. really find you need to modify the library itself, please communicate with
  171. me if possible first.
  172.  
  173.  
  174.  
  175. The IPC Protocol
  176. ================
  177.  
  178. As was said, this IPC mechanism is a general way for two (or more)
  179. processes to communicate quickly and conveniently, using "IPCMessages". The
  180. channels through which these messages are passed are "IPCPorts".
  181.  
  182. For clarity we talk about the original source of a message as a "Client",
  183. and the receiver that processes it as a "Server".  These terms are
  184. relative: a process may be a Client for one channel and a Server on
  185. another.  Often a process will spend a lot of its time processing the
  186. messages it receives on one channel by sending other requests out on other
  187. channels; I've taken to calling such a process a "Manager".
  188.  
  189. There is one particular Server that needs brief mention here, even though
  190. it is largely independent of the protocol itself -- the "Port Broker".  A
  191. Client may well request an IPCPort that isn't yet attached to a Server; it
  192. would be nice if this situation could be handled automatically, and this is
  193. in fact the function of the Port Broker.  This is a process that will be
  194. resident continuously; when a port is requested (by the "LoadIPCPort" call)
  195. that does not yet have a server, a message is sent to the broker, which
  196. looks up that port name in a list it has been provided with, and finds
  197. (and executes) the command needed to load a server for that port.  As with
  198. other Servers, there should eventually be a choice of Brokers for the user;
  199. there are a lot of functions in addition to the basic one that they could
  200. provide: more intelligent management of Servers (and possibly Clients) is
  201. one.  The "Broker" directory in this package contains a simple server and
  202. demo, and a more extensive discussion.
  203.  
  204.  
  205. The messages themselves can "contain" any information needed for the
  206. activity they are concerned with.  The quotation marks are because the
  207. information most often won't be in the message block itself but rather in a
  208. separate block pointed to by an item in the message.  (And remember that a
  209. message doesn't "move" when it is passed: it is simply put on a list in the
  210. IPCPort -- i.e. a couple of pointers are changed --  for the server to pick
  211. up.)
  212.  
  213. A message is "self-identifying".  A given IPCPort can handle many different
  214. types of IPCMessages, and the Server processing them will be able to
  215. determine immediately exactly what each contains.  It may alternatively
  216. find that it doesn't recognize the message, or some parts of it -- perhaps
  217. because the Client was assuming a more capable Server -- and will have to
  218. send it back with a rejection slip.
  219.  
  220. You get a number of levels of selection.  First, and most trivial, is the
  221. name of the IPCPort: a Client, before it can send messages to a port, will
  222. (normally) have to know its name; this can be any ASCII string, but we can
  223. expect that alternative Servers that provide equivalent functions will use
  224. ports with the same name.  This provides a first line of defence against
  225. wildly inappropriate messages, but it obviously is not nearly enough.  As
  226. we said, the Server must be able to determine the exact type from the
  227. message itself.  It does this from the "Message IDs", the "Item IDs", and
  228. to some extent from flags within the message.
  229.  
  230. Each message type has a specific 32-bit ID which exactly delimits its
  231. contents. The ID normally comprises four upper-case ASCII characters
  232. (exactly like an IFF ID word).  Some IDs are reserved to mean exactly the
  233. same thing across all servers.  Others will be meaningful only to
  234. particular Server functions; these should be chosen if possible not to
  235. clash with IDs used by others, but there should be little problem in
  236. practice if a clash does occur because they will be received by totally
  237. distinct Ports and Servers.
  238.  
  239. The internal structure of a message is totally consistent.  Within the
  240. message will be a number of "IPCItems", the exact count being specified in
  241. the header.  Each item has its own ID -- of exactly the same form as the
  242. message ID -- and always has the same (sixteen byte) structure, the most
  243. important element of which is a pointer to the data (if any).
  244.  
  245. A Server can quickly determine from scanning the various IDs what the
  246. message means, and can take the needed action.  If permitted by the
  247. context, it can write new data to some of the blocks in the message, or
  248. even fill empty slots in the message with new data (pointers).  It then
  249. replies the message to the original Client, and the transaction is
  250. complete.
  251.  
  252. IPCPorts -- and IPCMessages -- are managed by a resident shared library
  253. (IPC.lib), which must naturally be available in the LIBS: directory.
  254. Depending on the compiler you are using, you may need to include a small
  255. linkage module in your executable code to access the library functions (see
  256. the README file in the parent directory of this package).  All declarations
  257. and definitions needed for IPC are in IPC.h (suitable for all C compilers).
  258. For more information on the ways to incorporate IPC in the programs you
  259. write, please refer to the README file. A number of examples are also
  260. provided.
  261.  
  262. The following sections go into details of, first, the IPCPort mechanism,
  263. and then IPCMessages.
  264.  
  265.                             +++++++++++
  266.  
  267.  
  268. IPCPorts
  269. ========
  270.  
  271. An IPCPort is a rendezvous point between processes where messages can be
  272. dropped off and picked up.  It is identical in concept to the standard
  273. Amiga Exec MsgPort (see the Rom Kernel Manual), but is managed so that
  274. messages cannot be sent to a non-existent port (if the processes obey the
  275. rules!).  Any number of "Client" processes can be sending messages to a
  276. port at one time, but there can be only one "Server" on a port.  If a port
  277. doesn't have a Server -- either running or in the process of being loaded
  278. --, it is "Closed", and won't accept messages.
  279.  
  280. Unlike an Exec MsgPort, an IPCPort doesn't "belong" to any particular
  281. process, and a program must never create one directly or assign memory in
  282. its own space for one: a port will be created by the first process that
  283. needs it, and will remain available until all references to it have been
  284. cleared; it may be finally deleted by the last user long after the first
  285. has gone away. Either a Server or Client may make the first reference.
  286.  
  287. Each port is identified by a unique name (although unnamed anonymous ports
  288. are also possible, as we'll see later); the name may be any appropriate
  289. null-terminated byte string.  A port is located by an exact match to the
  290. string: the case of the characters is respected.  The author of a server
  291. will publish the names of the ports it services, so that others can write
  292. clients to access it; if two programs offer alternatives for the same
  293. service, they should use the same port name, so that the user may plug one
  294. of them in without changing the client.
  295.  
  296.  
  297. Clients and IPCPorts
  298. ====================
  299.  
  300. When a Client process first needs a port of a particular name, it must get
  301. a pointer to that port.  The pointer will then remain valid until the
  302. Client specifically drops its access request.  Each request made MUST be
  303. paired eventually with a drop, for correct port management.
  304.  
  305. There are three possible ways of getting a port pointer.  Each of these
  306. procedures takes a names string as argument and returns the pointer if
  307. possible.  They differ in the actions they take to ensure the status of the
  308. port.
  309.  
  310.     GetIPCPort(name)    always returns a valid pointer (unless memory is
  311.                         full, or some other disaster strikes).  The port is
  312.                         created if it doesn't exist.  No indication is
  313.                         given as to whether there is a current server.
  314.  
  315.     FindIPCPort(name)   only returns a pointer if the port already exists
  316.                         and has a server; otherwise it returns NULL.
  317.  
  318.     LoadIPCPort(name)   does a GetIPCPort, but if the port has no server
  319.                         it calls on a "Port Broker" process (only an early
  320.                         version of such is provided in the system at this
  321.                         stage) to load one; if the broker can't do this (or
  322.                         the broker doesn't exist) the port will be dropped
  323.                         again, and NULL will be returned.  If a valid
  324.                         pointer is returned, you can assume that a server
  325.                         exists or is being loaded.
  326.  
  327.                         LoadIPCPort does not wait for the server to be
  328.                         loaded, but the "Loading" flag will be set in the
  329.                         port so that it will accept messages for the server
  330.                         to handle when it arrives.
  331.  
  332.                         [The "Port Broker" Concept is intended as a core
  333.                         part of the IPC system, but has at this writing
  334.                         only been implemented in a simple form.  This is in
  335.                         its own directory in this suite, where you'll find
  336.                         more discussion.  I hope that others will develop
  337.                         Brokers of their own; this is, after all, the
  338.                         philosophy of IPC!]
  339.  
  340. Each successful call to one of these procedures increments the "Use Count"
  341. of the port.  To reduce the use count again you must end the Client's
  342. access to the port by:
  343.  
  344.     DropIPCPort(port)   where 'port' is the pointer returned by any of the
  345.                         above calls.  The use count is reduced by one: if
  346.                         it goes to zero, the port is deleted.
  347.  
  348. A Client must not exit without dropping all the ports it has acquired (and
  349. of course must not drop them more times than it has acquired them!).
  350.  
  351.  
  352. A Client sends messages to an IPCPort by a call exactly analogous to Exec's
  353. PutMsg(), but that Exec call has no way of detecting the presence or
  354. absence of a Server, so it should not be used.  Instead use:
  355.  
  356.     PutIPCMsg(port,message) where 'port' is a valid pointer, and 'message'
  357.                             is a pointer to an IPCMessage.  It returns TRUE
  358.                             if the message was successfully queued on the
  359.                             port; if the port has no server either present
  360.                             or loading, it will not send the message and
  361.                             will return FALSE.
  362.                             (If there are good reasons for bypassing the
  363.                             protocol -- as when an IPCPort is used as a
  364.                             reply port, see below -- a PutMsg (or ReplyMsg)
  365.                             call can be used, PROVIDED that you know that
  366.                             there is a Server, or will eventually be one;
  367.                             if there is no Server, one that attaches to the
  368.                             port later will pick up the message; on the
  369.                             other hand, if no Server ever finds the
  370.                             message, it (and the memory it occupies) will
  371.                             be gone forever.)
  372.  
  373. Unless there are specific reasons otherwise, a message sent to a Server
  374. will eventually be replied, and the Client must handle this also by
  375. supplying a Reply Port.  The reply path does not need the IPCPort protocol,
  376. because a Client MUST keep the reply port available until it has received
  377. back ALL the replies it is expecting, so normally this can be a standard
  378. Exec MsgPort.  There is no reason though why it should not be an IPCPort as
  379. well if you prefer -- even one used for other communications -- as long as
  380. you bear in mind that replies will be sent to it whether or not it has a
  381. server assigned.
  382.  
  383.  
  384. Servers and IPCPorts
  385. ====================
  386.  
  387. The Server uses a complementary set of procedures to a Client to manage a
  388. port.  There is only one way it can acquire a port:
  389.  
  390.     ServeIPCPort(name)  makes this process the server for the named port
  391.                         if possible and returns a valid pointer to the
  392.                         port. The port is created if it doesn't exist.  If
  393.                         a server already exists for the port, the call will
  394.                         return NULL. (If successful, it also increments the
  395.                         use count.)
  396.  
  397. Terminating service on the other hand is normally a two-step process.
  398. First the server must shut the port against further incoming messages, then
  399. handle and reply to any messages still queued on the port, and finally free
  400. up the port for eventual reclamation or for another server to claim it.
  401.  
  402.     ShutIPCPort(port)   just marks the port as "Shut".  The server remains
  403.                         attached to the port and can receive signals from
  404.                         it (for example if the number of clients changes,
  405.                         see below), but PutIPCMsg calls will be blocked.
  406.  
  407.     LeaveIPCPort(port)  removes this process from association with the
  408.                         port.  Also does a DropIPCPort to decrement the use
  409.                         count and delete if appropriate.
  410.  
  411. Between the ServeIPCPort and the ShutIPCPort, the server must be prepared
  412. to accept messages on that port.  In most cases it will probably spend the
  413. major portion of its time waiting on that port -- or possibly several ports
  414. -- for a message to arrive.  All this area of the server's operation is
  415. handled by standard Exec calls: WaitPort() or Wait(), GetMsg(), and
  416. ReplyMsg() (see the Rom Kernel Manual).
  417.  
  418. If it only has one port to wait on, it can use:
  419.  
  420.     WaitPort(port)  which suspends the process until a message arrives at
  421.                     that port.
  422.  
  423. This is liable to be inadequate though, because it will only be woken up by
  424. messages arriving on that particular port.  It is NOT awakened by other
  425. signals to the process, even if they use the same signal bit (see the RKM
  426. for Task Signals).  Thus you are more likely to want to use:
  427.  
  428.     Wait(sigbits)   where 'sigbits' is a 32-bit mask of all the signals you
  429.                     want to be awakened on.  It returns the signals that
  430.                     were actually set, so the process can determine if it
  431.                     needs to take unusual action.
  432.  
  433. This means, though, that you have to create the sigbits mask from the
  434. signal bit number contained in the port itself (and other bits that you
  435. want to respond to).  There is no specific call to get this (though there
  436. should probably be at least a macro), but if the server is just using IPC.h
  437. as a header (without IPCPorts.h -- which should only be needed for IPC
  438. system management programs) IPCPorts are equated to MsgPorts, so you can
  439. get the bit by:
  440.  
  441.     sigbit = 1L<<port->mp_SigBit;
  442.  
  443. Note that this bit is also used by the "Notify" feature (below) to awaken
  444. the server if the number of clients changes.  No message is associated with
  445. this signal, but all the server has to do is check the number of clients
  446. (again, below) each time it is awakened.
  447.  
  448. To process a received message, the server simply uses GetMsg(), though it
  449. is preferable to cast the returned value to the correct type:
  450.  
  451.     msg = (struct IPCMessage *)Getmsg(port);
  452.  
  453. When done with the message, it should use ReplyMsg() in the normal way
  454. (again using a cast, preferably):
  455.  
  456.     ReplyMsg((struct Message *)msg);
  457.  
  458.  
  459. Checking IPCPort Status
  460. =======================
  461.  
  462. Either Client or Server can get information about the current state of an
  463. IPCPort with the CheckIPCPort() call.  The Server alone can also set
  464. the state of certain flags in the port (only one is currently defined).
  465.  
  466.     CheckIPCPort(port,flags)    as long as the high bit of 'flags'
  467.                                 (a 16-bit value!) is not set, returns the
  468.                                 number of users (including the server)
  469.                                 currently aware of the port; if the high
  470.                                 bit is set (0x8000 -- this should be a
  471.                                 defined identifier... an omission in the
  472.                                 current IPC.h, sorry), the call instead
  473.                                 returns the current flags set in the port.
  474.                                 When called by the current Server ONLY, the
  475.                                 value in the low 8-bits of the 'flags'
  476.                                 argument will be set into the port's Flags
  477.                                 slot; system flags in the upper 8-bits of
  478.                                 the slot are not affected.
  479.  
  480. Although a Client may use this call, it will probably have no need to,
  481. unless it wants to check for the presence of a Server without making a
  482. PutIPCMsg call.  The Server, however, can use the call to keep tabs on how
  483. many clients actually require its services, and optionally terminate if
  484. there are none.  To do this it will want to be notified if the number of
  485. clients changes; this can be done by setting the IPP_NOTIFY flag in the
  486. port: while that is set, any call that acquires or drops a port will send a
  487. signal to the Server process (using the signal bit defined for that message
  488. port); no message is actually sent, but the Server should call CheckIPCPort
  489. each time it is woken up.
  490.  
  491.  
  492. Anonymous IPCPorts
  493. ==================
  494.  
  495. It is possible to create IPCPorts that are unnamed, but these obviously
  496. cannot be acquired independently by other processes without a name to
  497. access them by.  The associated pointers must be passed to other processes
  498. via some standard message pathway (see the companion document on Standard
  499. IDs). They still should obey the IPC rules, though, so another procedure is
  500. provided for acquiring a port passed as a pointer:
  501.  
  502.     UseIPCPort(port)    registers another user for that port (i.e.
  503.                         increments the use count).
  504.  
  505. (Note that you are not restricted to passing pointers to unnamed ports, and
  506. UseIPCPort can be applied to ANY IPCPort when a process has its pointer
  507. rather than its name.)
  508.  
  509. When the user process is done, it issues DropIPCPort in the usual way.
  510.  
  511. You create an anonymous IPCPort by:
  512.  
  513.     ServeIPCPort(NULL)  which will return a pointer to a NEW port for
  514.                         each call, and set the caller as the Server.
  515.                         (It will only fail if there is no memory or some
  516.                         such fatal problem.)
  517.  
  518. For special cases -- e.g. ReplyPorts -- where you know PutIPCMsg will never
  519. be used, you could instead use GetIPCPort(NULL), but there is NO way of
  520. registering a server on an anonymous port except at creation time.
  521.  
  522.                             +++++++++++
  523.  
  524. IPCMessages
  525. ===========
  526.  
  527. The format of IPCMessages is intended to be very flexible, yet specific
  528. enough that a Server can immediately determine the function and content of
  529. a message it receives (or reject it if it does not recognize it).
  530.  
  531. The protocol has two levels where identification is specified.  There is a
  532. fixed structure Message header (basically an Exec Message structure with
  533. added information) which includes a Message ID, followed by an arbitrary
  534. number of "Items", each again of fixed structure with its own Item ID.
  535. Each item in turn usually points to a block of memory where the actual data
  536. for the item is stored.  Instead of a pointer, a single 32-bit value can be
  537. stored in the item itself.  In special cases, the data pointed to may be
  538. more complex than a single data block (a list, say) but then the
  539. restrictions on what can be done with the message increase markedly.
  540. As long as all the items in a message are simple data blocks (or single
  541. words), it can be passed between servers that do not have to understand the
  542. contents of those blocks: deletion of the message, for example can be done
  543. by any server.  Flags in the message and each item indicate whether the
  544. data is private to the originating process or can be transferred to the
  545. receiver, whether it is suitable to send out on a network, and so on.
  546.  
  547. An ID -- Message or Item -- is a 32-bit longword, normally a four-character
  548. ASCII code.  All "Published" IDs should be of this form, but cooperating
  549. processes could perhaps use non-ASCII numeric values internally.  If the
  550. first (high) byte is zero, the ID is a private one.  Codes of less than
  551. four characters may of course be used, but they preferably should be padded
  552. on the right with blanks (rather than nulls).  Case is important naturally;
  553. by convention (and analogy to IFF) upper case is preferred, but there is no
  554. firm requirement for this; lower case should probably be used to extend on
  555. meanings that were originally upper case.
  556.  
  557. For details on IPCMessage structure, and the various flags currently
  558. defined, please refer to the IPC.h header file (and see the following
  559. section).  A full description of the flags is in the accompanying document
  560. "Standard Flags".  A list of the currently reserved IDs, and others of more
  561. specific utility, is in "Standard IDs".  For the ways these IDs (or some of
  562. them) have been used, look at the demo example sources in this package.
  563. When you develop your own Servers, you will of course immediately need to
  564. assign your own IDs; please do it with future expansion in mind, and
  565. publish them on usenet or elsewhere as soon as possible for comment.
  566.  
  567.  
  568. Message Structure
  569. =================
  570.  
  571. This section is just a restatement (and maybe clarification) of the
  572. information in IPC.h. Please look at that file also.
  573.  
  574. Each message has a header which is a standard message structure, followed
  575. by an ID field (32-bits), a 32-bit Flags field, and an Item Count
  576. (16-bits).  This is immediately followed by that number of items, each of
  577. which has the following structure:  Item ID (32-bits), Flags (32-bits),
  578. Size of data block (32-bits), and Pointer to data block (also of course
  579. 32-bits). This may in turn be followed by a data area containing the data
  580. for some or all of the items in a message; putting data here may or may not
  581. be convenient, depending on the nature of the data.  The mn_Length field in
  582. the standard message structure indicates the complete length of the message
  583. (remember it is only 16-bits, so the maximum size of a message containing
  584. in-line data is 64K).
  585.  
  586. As already remarked, the "Pointer" field of an item usually points to a
  587. single block of data, but it may represent other things as well.  It may be
  588. a single value, or a non-standard item (a BPTR for example).  In these
  589. cases, the Size of the item should be set to ZERO.  As long as the Server
  590. only has to treat the item as a value or a handle, this is all that needs
  591. to be done.  In other situations it may be a true pointer to data which the
  592. Server must deal with, but the data referenced may NOT be a simple data
  593. block (created by AllocMem); it could be a list structure, for instance, or
  594. it could be itself a structure which contains pointers to other data.  If
  595. this is so, the IPC_NONSTANDARD flag must also be set, so that "ignorant"
  596. servers won't do anything silly.  The contents of the Size field here will
  597. depend on the function of the item, but most often it will probably be
  598. zero.
  599.  
  600.  
  601.  
  602. Managing IPCMessages
  603. ====================
  604.  
  605. Two system procedures are provided for convenient management of memory for
  606. IPCMessages (much preferable to the program doing it all for itself).
  607.  
  608.     CreateIPCMsg(items, extra, replyport)   creates a new message block
  609.                                             for that number of 'items'
  610.                             (0..n), with 'extra' bytes of memory after the
  611.                             items for data storage (you will have to get
  612.                             its offset as the location of the "item"
  613.                             following the last actual item); the
  614.                             'replyport' pointer is inserted in the standard
  615.                             message structure.  A pointer to the created
  616.                             message (or NULL if there is no space) is
  617.                             returned.
  618.  
  619.     DeleteIPCMsg(msg)       deletes the memory block created by
  620.                             CreateIPCMsg.  It does NOT attempt to handle
  621.                             memory occupied by data outside the message and
  622.                             pointed to by its items.
  623.  
  624.  
  625.                             +++++++++++
  626.  
  627.  
  628. Other Library Functions
  629. =======================
  630.  
  631. Two other functions have been added to the library for user convenience:
  632.  
  633.     MakeIPCId(string)       returns a longword ID value constructed from
  634.                             the characters in the supplied string.  The
  635.                             string should normally be four uppercase ASCII
  636.                             characters; if you supply fewer they will be
  637.                             high-bit ("left") justified and padded with
  638.                             NULLS (but see notes on preferred IDs above);
  639.                             more will just be truncated. This function will
  640.                             be useful for programs whose set of IDs is not
  641.                             fixed at compile time (they might read them
  642.                             perhaps from a setup file).
  643.  
  644.     FindIPCItem(msg, ID, firstitem)     returns a pointer to the first item
  645.                                         found in 'msg' that matches 'ID'
  646.                             (NULL if none is found).  If 'firstitem' is not
  647.                             NULL, it MUST be a valid pointer to an item in
  648.                             the message, and the search will begin from
  649.                             (and include) that item; if it is NULL, the
  650.                             search will begin from the first item in the
  651.                             message.  If you are doing successive searches
  652.                             for the same ID, remember to increment the
  653.                             'firstitem' pointer before the next call --
  654.                             otherwise the same item will be returned
  655.                             repeatedly!
  656.  
  657.  
  658.  
  659.                             +++++++++++
  660.  
  661.                                             Pete Goodeve
  662.                                             November 1989
  663.  
  664.